/*
* Poppy Game Engine - https://pgetemplate.googlecode.com/svn/
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* Copyright (c) 2008 Poppy
*/

#include "stdafx.h"
#include "IThread.h"

namespace PGESystem
{

	int IThread::Run()
	{
		m_eThreadState = THREAD_IS_RUNNING;
		int res = ThreadEntry();
		m_eThreadState = THREAD_HAS_EXITED;
		return res;
	}

	void IThread::Sleep( PGE_Uint millisecond )
	{
		PGE_SleepMilliseconds(millisecond);
	}

	void IThread::Exit( IThread* thread, PGE_Uint exitcode )
	{
		thread->m_eThreadState = THREAD_HAS_EXITED;
		PGE_ExitThread(exitcode);
	}

	PGE_Uint IThread::GetId()
	{
		return PGE_GetThreadId();
	}

	int IThread::GetCurrentPriority()
	{
		return PGE_GetCurrentThreadPriority();
	}

	void IThread::Jointhread( IThread* thread )
	{
		PGE_WaitThreadFinish(thread->m_hThreadHandle);
	}

	IThread::IThread( LPCSTR name, int size, int priority, PGE_Uint attr )
	{
		m_pThreadName = name;
		m_dStackSize = size;
		m_dPriority = priority;
		m_dInitAttr = attr;
		m_hThreadHandle = 0;
		m_pPRunnable = this;
		m_eThreadState = THREAD_BEFORE_INIT;
	}

	bool IThread::InitThread()
	{
		if(m_eThreadState != THREAD_BEFORE_INIT) return false;
		m_hThreadHandle = PGE_CreateThread( m_pThreadName, &m_pPRunnable, m_dStackSize, m_dPriority, m_dInitAttr );
		if( SUCCEED_METHOD(m_hThreadHandle) )
		{
			m_eThreadState = THREAD_BEFORE_START;
			return true;
		}
		return false;
	}

	bool IThread::StartThread()
	{
		if(m_eThreadState != THREAD_BEFORE_START) return false;
		PGE_StartThread(m_hThreadHandle, &m_pPRunnable);
		return true;
	}

	bool IThread::GoThread()
	{
		return (InitThread()&&StartThread());
	}

	bool IThread::TerminateThread()
	{
		if(PGE_TerminateThread(m_hThreadHandle))
		{
			m_eThreadState = THREAD_HAS_EXITED;
			return true;
		}
		return false;
	}

	bool IThread::DestoryThread()
	{
		if( m_eThreadState == THREAD_IS_RUNNING || m_eThreadState == THREAD_IS_WAITING )
			TerminateThread();
		if(PGE_DeleteThread(m_hThreadHandle))
		{
			m_eThreadState = THREAD_BEFORE_INIT;
			return true;
		}
		return false;
	}

	PGE_Uint IThread::GetExitStatus()
	{
		return PGE_GetExitStatus(m_hThreadHandle);
	}

	bool IThread::Wait()
	{
		if(m_eThreadState==THREAD_IS_RUNNING)
		{
			PGE_SuspendThread(m_hThreadHandle);
			m_eThreadState = THREAD_IS_WAITING;
			return true;
		}
		return false;
	}

	bool IThread::Notify()
	{
		if(m_eThreadState==THREAD_IS_WAITING)
		{
			PGE_ResumeThread(m_hThreadHandle);
			m_eThreadState = THREAD_IS_RUNNING;
			return true;
		}
		return false;
	}

	bool IThread::SetPriority( int priority )
	{
		if(m_eThreadState != THREAD_IS_WAITING) return FALSE;
		m_dPriority = priority;
		return PGE_SetThreadPriority(m_hThreadHandle, m_dPriority);
	}

	bool IThread::ExaltPriority( int step )
	{
		if(m_eThreadState != THREAD_IS_WAITING) return false;
		m_dPriority += step;
		return PGE_SetThreadPriority(m_hThreadHandle, m_dPriority);
	}

	bool IThread::DebasePriority( int step )
	{
		if(m_eThreadState != THREAD_IS_WAITING) return FALSE;
		m_dPriority -= step;
		return PGE_SetThreadPriority(m_hThreadHandle, m_dPriority);
	}

	LPCSTR IThread::GetThreadName() const
	{
		return m_pThreadName;
	}

	int IThread::GetStackSize() const
	{
		return m_dStackSize;
	}

	int IThread::GetPriority() const
	{
		return m_dPriority;
	}

	PGE_Uint IThread::GetInitAttr() const
	{
		return m_dInitAttr;
	}

	int IThread::GetThreadState() const
	{
		return m_eThreadState;
	}

	IThread::~IThread()
	{
		if(m_eThreadState != THREAD_BEFORE_INIT) DestoryThread();
	}

	void IThread::Join()
	{
		PGE_WaitThreadFinish(m_hThreadHandle);
	}

}
